const core = require('@babel/core')
const arrowFunctionPlugin = require('babel-plugin-transform-es2015-arrow-functions')
const types = require('@babel/types')

let sourceCode = `
  const sum = (a, b) => {
    console.log(this)
    return a + b
}
`

function hoistFunctionEnvironment(path) {
  const thisEnv = path.findParent((parent) => {
    // 父级是函数 并且不是箭头函数 或者 根节点
    return (
      (parent.isFunction() && !parent.isArrowFunctionExpression()) ||
      parent.isProgram()
    )
  })

  thisEnv.scope.push({
    id: types.identifier('_this'),
    init: types.thisExpression(),
  })

  let thisPaths = []

  path.traverse({
    ThisExpression(path) {
      thisPaths.push(path)
    },
  })

  thisPaths.forEach((path) => {
    path.replaceWith(types.identifier('_this'))
  })
}

const myArrowFunction = {
  visitor: {
    ArrowFunctionExpression(path) {
      const { node } = path
      path.node.type = 'FunctionExpression'

      hoistFunctionEnvironment(path)

      // 处理 简写缺少块级作用域
      if (!types.isBlockStatement(path.node.body)) {
        node.body = types.BlockStatement([types.ReturnStatement(node.body)])
      }
    },
  },
}

let { code } = core.transform(sourceCode, {
  plugins: [myArrowFunction],
})
console.log(code)

/*
 * var _this = this
 * const sum = function (a, b) {
 *   return a + b
 * }
 */
